package pikes.peak;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import pikes.html.xhtml.Block;
import pikes.html.xhtml.Division;
import pikes.html.xhtml.text.HorizontalRule;
import org.springframework.web.servlet.support.RequestContext;

public class Composite implements BlockComponent {

	public static final BlockComponent LINE = new BlockComponent() {

		public Block createHtml(Map model, RequestContext requestContext) throws Exception {
			return new HorizontalRule();
		}

	};

	private CharSequence name = null;

	private CharSequence clazz = null;

	private List<Selector<Component>> selectors = new LinkedList<Selector<Component>>();

	public Composite() {

	}

	public Composite(CharSequence name) {
		this.name = name;
	}

	public CharSequence getClazz() {
		return clazz;
	}

	public void setClazz(CharSequence clazz) {
		this.clazz = clazz;
	}

	public void add(Component component) {
		if (component != null) {
			selectors.add(new Selector<Component>(component));
		}
	}

	public Block createHtml(Map model, RequestContext requestContext) throws Exception {
		Division division = new Division();

		if (name != null) {
			division.setId(name);
		}

		if (clazz != null) {
			division.setClazz(clazz);
		}

		List<Component> components = new LinkedList<Component>();

		for (Selector<Component> selector : selectors) {
			selector.select(components, model, requestContext);
		}

		for (Component component : components) {
			division.add(component.createHtml(model, requestContext));
		}

		return division;
	}

	public void add(Component component, VisibilityCondition visibilityCondition) {
		if (component != null) {
			selectors.add(new Selector<Component>(visibilityCondition, component));
		}

	}

}

class Selector<E extends Component> {

	private E component = null;

	private VisibilityCondition condition = VisibilityCondition.YES;

	public Selector(E component) {
		this(VisibilityCondition.YES, component);
	}

	public Selector(VisibilityCondition condition, E component) {
		this.condition = condition;
		this.component = component;
	}

	public void select(List<E> components, Map model, RequestContext requestContext) throws Exception {
		if (condition.isTrue(model, requestContext)) {
			components.add(component);
		}
	}
}